package business_logic;


import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import model.exceptions.ModelExceptions;
import fiuba.algo3.titiritero.dibujables.SuperficiePanel;
import fiuba.algo3.titiritero.modelo.SuperficieDeDibujo;

public class MainWindow
{

	private JFrame m_frame;
    private JButton m_btnPauseContinue;
    private JButton m_btnLoadGame;
    private JButton m_btnSaveGame;
    private JButton m_btnNewGame;
    protected boolean m_gameStarted = false;

	private static final int WINDOWS_WIDTH = 640; 
    private static final int WINDOWS_HEIGHT = 480;
    
    private static final int SCALE_FACTOR   = 20;
    private static final int TILES_X = 30;
    private static final int TILES_Y = 20;
    
    private static final int VIEW_WEIGTH    = TILES_X * SCALE_FACTOR;
    private static final int VIEW_HEIGHT    = TILES_Y * SCALE_FACTOR;
    private static final Color MAIN_PANEL_BACKGROUND_COLOR = Color.BLACK;
    
    private static final int BUTTON_WEIGTH  = 100;
    private static final int BUTTON_HEIGHT  = 20;
    private static final int BUTTON_IDENTATION  = 60;
    private static final int BUTTON_SEPARATION  = 40;
    private static final int BUTTON_YPOSITION   = WINDOWS_HEIGHT - 35;
    
    private static final String NEW_GAME_BUTTON_TEXT = "New Game";
    private static final String CONTINUE_BUTTON_TEXT = "Continue";
    private static final String PAUSE_BUTTON_TEXT    = "Pause";
    private static final String LOAD_BUTTON_TEXT     = "Load";
    private static final String SAVE_BUTTON_TEXT     = "Save";
    
    private static final String CUSTOM_SAVEGAME_FILENAME = "savedGame.xml";
    
    private static Game m_game;
    
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) 
	{
        //Game.configure();

	    EventQueue.invokeLater ( new Runnable() 
        {
            public void run() 
			{
				try 
				{
					MainWindow window = new MainWindow();
					window.m_frame.setVisible(true);
					window.m_frame.repaint();
				} 
				catch (Exception e) {
					e.printStackTrace();
				}
			}
        });
	}

	/**
	 * Create the application.
	 * @throws ModelExceptions 
	 */
	public MainWindow()
	{
		try
		{
			initialize();
		} 
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Initialize the contents of the frame.
	 * @throws IOException 
	 * @throws ModelExceptions 
	 */
	private void initialize() throws IOException, ModelExceptions
	{
		m_frame = new JFrame();
		m_frame.setForeground(new Color(0, 0, 0));
		m_frame.setBounds(0, 0, WINDOWS_WIDTH, WINDOWS_HEIGHT+20);
		m_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		m_frame.getContentPane().setLayout(null);
		m_frame.setResizable(false);
		
		// TODO: revisar si esto va aca...
		Tile.setSize(SCALE_FACTOR);
		JPanel mainPanel = new SuperficiePanel();
        mainPanel.setBackground(MAIN_PANEL_BACKGROUND_COLOR);
        mainPanel.setBounds(20, 10, VIEW_WEIGTH, VIEW_HEIGHT+30);   // Agregado el tamaño de la scoreBar
		m_game = new Game(TILES_X,TILES_Y,(SuperficieDeDibujo) mainPanel);
		
		m_btnNewGame = new JButton(NEW_GAME_BUTTON_TEXT);
		m_btnNewGame.addActionListener ( new ActionListener() 
        {
            public void actionPerformed(ActionEvent arg0) 
            {
                m_gameStarted = true;
                m_btnPauseContinue.setEnabled(true);
                m_btnSaveGame.setEnabled(true);
                m_game.newGame();
                m_game.resume();
            }
        });
		
		m_btnNewGame.setBounds(BUTTON_IDENTATION-10, BUTTON_YPOSITION, BUTTON_WEIGTH+10, BUTTON_HEIGHT);
        m_frame.getContentPane().add(m_btnNewGame);
		
        m_btnPauseContinue = new JButton(PAUSE_BUTTON_TEXT);
        m_btnPauseContinue.addActionListener ( new ActionListener()
        {
            private boolean m_isPauseBtn = true;
            
            public void actionPerformed(ActionEvent e)
            {
                if( m_isPauseBtn )
                {
                    if( m_game.pause() )
                        this.transformIntoContinueBtn();
                }
                else
                {
                    if ( m_game.resume() )
                        this.transformIntoPauseBtn();
                }
            }
            
            private void transformIntoPauseBtn()
            {
                m_btnPauseContinue.setText(PAUSE_BUTTON_TEXT);
                m_isPauseBtn = true;
                m_btnNewGame.setEnabled(true);
                m_btnLoadGame.setEnabled(true);
            }
            
            private void transformIntoContinueBtn()
            {
                m_btnPauseContinue.setText(CONTINUE_BUTTON_TEXT);
                m_isPauseBtn = false;
                m_btnNewGame.setEnabled(false);
                m_btnLoadGame.setEnabled(false);
            }
        });
		
        m_btnPauseContinue.setBounds(BUTTON_IDENTATION+(BUTTON_WEIGTH+BUTTON_SEPARATION)*1, BUTTON_YPOSITION, BUTTON_WEIGTH, BUTTON_HEIGHT);
		m_frame.getContentPane().add(m_btnPauseContinue);
		
		m_btnLoadGame = new JButton(LOAD_BUTTON_TEXT);
		m_btnLoadGame.addActionListener ( new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                m_gameStarted = true;
                m_game.loadCustomGame(CUSTOM_SAVEGAME_FILENAME);
                m_btnPauseContinue.setEnabled(true);
                m_btnSaveGame.setEnabled(true);
                if ( !m_game.isRunning() )
                    m_game.resume();
            }
        });
		
		m_btnLoadGame.setBounds(BUTTON_IDENTATION+(BUTTON_WEIGTH+BUTTON_SEPARATION)*2, BUTTON_YPOSITION, BUTTON_WEIGTH, BUTTON_HEIGHT);
        m_frame.getContentPane().add(m_btnLoadGame);
		
        m_btnSaveGame = new JButton(SAVE_BUTTON_TEXT);
        m_btnSaveGame.addActionListener ( new ActionListener() 
        {
            public void actionPerformed(ActionEvent e)
            {
                m_game.saveCustomGame(CUSTOM_SAVEGAME_FILENAME);
            }
        });
        
        m_btnSaveGame.setBounds(BUTTON_IDENTATION+(BUTTON_WEIGTH+BUTTON_SEPARATION)*3, BUTTON_YPOSITION, BUTTON_WEIGTH, BUTTON_HEIGHT);
        m_frame.getContentPane().add(m_btnSaveGame);

		m_frame.getContentPane().add(mainPanel);
		
		m_btnSaveGame.setEnabled(false);
		m_btnPauseContinue.setEnabled(false);
		
		m_game.resume();
		
		/** INICIO: Eventos de mouse y teclado **/
		
		mainPanel.addMouseListener ( new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent arg0)
			{
			    if(m_game.isRunning())
                {
                }
			}
		});

		m_frame.setFocusable(true);
		m_btnPauseContinue.setFocusable(false);
		m_btnNewGame.setFocusable(false);
		m_btnLoadGame.setFocusable(false);
        m_btnSaveGame.setFocusable(false);
        
        /*
        try
        {
            Thread.sleep(1000);
            m_game.showScoreBoard();
        }
        catch (InterruptedException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        */
        
		m_frame.addKeyListener ( new KeyListener() 
        {	
			private void addPlayerCommand(KeyEvent arg0)  
			{			
		        switch( arg0.getKeyCode() )
		        {
		            case KeyEvent.VK_LEFT:
		            case KeyEvent.VK_A:
		                m_game.playerMovesLeft();
		                break;
		                
		            case KeyEvent.VK_RIGHT:
		            case KeyEvent.VK_D:
		                m_game.playerMovesRight();
		                break;
		                
		            case KeyEvent.VK_UP:
		            case KeyEvent.VK_W:
		                m_game.playerMovesUp();
		                break;
		                
		            case KeyEvent.VK_DOWN:
		            case KeyEvent.VK_S:
		                m_game.playerMovesDown();
		                break;
		                
		            case KeyEvent.VK_SPACE:
		                m_game.playerDropsBomb();
		                break;

		            case KeyEvent.VK_N:
		                
		                if(  m_game.isRunning() && m_gameStarted )
		                {		                    
		                    m_game.forceWinLevel();
		                    System.out.println( "CHEATER!" );
		                }
		                break;
		            
		            case KeyEvent.VK_P:
		                m_btnPauseContinue.doClick();
                      break;
		            
		            case KeyEvent.VK_R:
		                m_btnNewGame.doClick();
		                break;

		            default:
		                //m_game.playerStops();
		        }			        
				
		        if ( m_game.isRunning() )
		            m_game.PlayerWinning(Konami.checkKonami( arg0.getKeyCode() ));
			}
			
			@Override
			public void keyTyped(KeyEvent arg0) 
			{
			    //System.out.println("Key pressed: '"+arg0.getKeyChar()+"'");
			}
			
			@Override
			public void keyReleased(KeyEvent arg0) 
			{
			}
			
			@Override
			public void keyPressed(KeyEvent arg0) 
			{
			    //System.out.println("Ping");
			    //System.out.println("Key pressed: '"+arg0.getKeyCode()+"'");
			    
			    addPlayerCommand(arg0);
			    
			}
	    });
		
		/** FIN: Eventos de mouse y teclado **/
		
		/** PATCH PARA QUE NO SE CUELGUE EL GAMELOOP CUANDO MOSTRAMOS EL SCORE_BOARD **/
		// Según: http://stackoverflow.com/questions/3072173/how-to-call-a-method-after-a-delay
		ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();

        Runnable task = new Runnable()
        {
            public void run()
            {
                m_game.showScoreBoard();
            }
        };
        
        worker.schedule(task, 1, TimeUnit.SECONDS);
		
	}
}
